#!/bin/bash
# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH

# 使用说明

# 1、各种补全：路径补全、命令补全，命令参数补全，插件内容补全等等。
## 触发补全只需要按一下或两下 tab 键，补全项可以使用 ctrl+n/p/f/b上下左右切换。
## 例1: 你想杀掉 java 的进程，只需要输入 kill java + tab键，如果只有一个 java 进程，zsh 会自动替换为进程的 pid，如果有多个则会出现选择项供你选择。
## 例2: ssh + 空格 + 两个tab键，zsh会列出所有访问过的主机和用户名进行补全

# 2、智能跳转，安装了autojump之后，zsh 会自动记录你访问过的目录，通过 j + 目录名 可以直接进行目录跳转，而且目录名支持模糊匹配和自动补全
## 例1: 如访问过hadoop-1.0.0目录，输入j hado 即可正确跳转。
## 例2: j –stat 可以看你的历史路径库。

# 3、目录浏览和跳转：输入 d，即可列出你在这个会话里访问的目录列表，输入列表前的序号，即可直接跳转。

# 4、在当前目录下输入 .. 或 … ，或直接输入当前目录名都可以跳转，你甚至不再需要输入 cd 命令了。

#> 参考资料
# - [终极 Shell——ZSH](https://zhuanlan.zhihu.com/p/19556676)
# - [为什么说 zsh 是 shell 中的极品？](https://www.zhihu.com/question/21418449)
# - [Mac安装oh my zsh插件autojump、zsh-syntax-highlighting、zsh-autosuggestion](https://www.jianshu.com/p/bd9ea233f933?utm_campaign=haruki)
# - [快速安装oh-my-zsh的插件zsh-syntax-highlighting 语法高亮](https://blog.csdn.net/shenhonglei1234/article/details/106676481)

# 关闭每天会在第一次打开时进行自动更新检测（需要开启时注释掉）
DISABLE_AUTO_UPDATE="true" 

# 手动更新呢？请执行下面的命令即可：
# upgrade_oh_my_zsh 或 omz update
# 当然也可以通过下面的方式来进行检查更新：
# zsh ~/.oh-my-zsh/tools/check_for_upgrade.sh

# 解决zsh:zsh: command not found:
# source ~/.bash_profile

# 解决zsh:zsh: command not found fzf:
PATH=$PATH:$HOME/bin
export PATH

[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh

# 添加相应命令所在路径到环境变量中 
# 先查找 find / -name "命令工具名"
# export PATH=~/.npm-global/bin:${PATH}:/usr/local/bin

# ruby
# If you need to have ruby first in your PATH run:
#   echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc
# For compilers to find ruby you may need to set:
#   export LDFLAGS="-L/usr/local/opt/ruby/lib"
#   export CPPFLAGS="-I/usr/local/opt/ruby/include"
export PATH="/usr/local/opt/ruby/bin:$PATH"

# 检查与安装 oh-my-zsh   Install oh-my-zsh if not exist
OHMYZSH="$HOME/.oh-my-zsh"
if [ ! -d "$OHMYZSH" ]; then
  echo "Installing oh-my-zsh ..."
  URL="https://github.com/robbyrussell/oh-my-zsh.git"
  if [ -x "$(which git)" ]; then
    echo "git 克隆 oh-my-zsh 到 ~/.oh-my-zsh"
    git clone "$URL" "$OHMYZSH"
  else
    echo "ERROR: please install git  before installation !!"
    exit
  fi
  if [ ! $? -eq 0 ]; then
    echo ""
    echo "ERROR: downloading oh-my-zsh ($URL) failed !!"
    exit
  fi;
  echo "move $TMPFILE to $ANTIGEN"
fi

# Path to your oh-my-zsh installation.
export ZSH="${HOME}/.oh-my-zsh"

# Set name of the theme to load --- if set to "random", it will
# load a random theme each time oh-my-zsh is loaded, in which case,
# to know which specific one was loaded, run: echo $RANDOM_THEME
# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
ZSH_THEME="clean" # set by `omz`

# 插件
# 安装插件 zsh-syntax-highlighting 
# git clone https://hub.fastgit.org/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions
# 安装插件 zsh-syntax-highlighting 
# git clone https://hub.fastgit.org/zsh-users/zsh-syntax-highlighting $ZSH_CUSTOM/plugins/zsh-syntax-highlighting

plugins=(
  git
  vi-mode
  zsh-autosuggestions
  zsh-history-substring-search
  fast-syntax-highlighting
)
#zsh-syntax-highlighting
source $ZSH/oh-my-zsh.sh

# 插件配置
## z.lua 配置
### ZSH 初始化
eval "$(lua ~/.config/z.lua/z.lua --init zsh enhanced once echo)" 

# - 设置 `$_ZL_CMD` 来改变命令名称 (默认为 z)。
# - 设置 `$_ZL_DATA` 来改变数据文件 (default ~/.zlua)。
# - 设置 `$_ZL_NO_PROMPT_COMMAND` 为 1 来跳过钩子函数初始化（方便自己处理）。
# - 设置 `$_ZL_EXCLUDE_DIRS` 逗号分隔的路径列表，列表内的路径不会被收集。
# - 设置 `$_ZL_ADD_ONCE` 为 '1' 时，仅在当前路径 `$PWD` 改变时才更新数据库。
# - 设置 `$_ZL_MAXAGE` 来确定一个数据老化的阀值 (默认为 5000)。
# - 设置 `$_ZL_CD` 用来指定你想用的 cd 命令，比如有人用 cd_func 。
# - 设置 `$_ZL_ECHO` 为 1 可以在跳转后显示目标路径名称。
# - 设置 `$_ZL_MATCH_MODE` 为 1 可以打开 “增强匹配模式”。
# - 设置 `$_ZL_HYPHEN` 为 1 可以允许关键字中包含横线 （横线默认是 lua 正则关键字，要转写成 `%-`）。

alias zh='z -I -t .'   # 回到历史路径，用 fzf 进行历史路径操作
alias zi='z -i'        # 使用交互式选择模式
alias zf='z -I'        # 使用 fzf 对多个结果进行选择
alias zb='z -b'        # 快速回到父目录

## autojump 配置
# [ -f /usr/local/etc/profile.d/autojump.sh ] && . /usr/local/etc/profile.d/autojump.sh

#fast-syntax-highlighting
# 自定义命令
# 使用cd fd fzf 查找与切换vim文件
vimf(){
    vim $(fzf --preview 'cat -n {}')
}
nvimf(){
    nvim $(fzf --preview 'cat -n {}')
}

# 使用cd fd fzf 查找与切换目录
cdf(){
   # cd $(fd -p '/' -t d | fzf )
   # cd $(fd -p ’/‘ -t d | fzf --preview 'ls -alh {}')
   cd $(fd  -t  d | fzf --preview 'ls -ahl {}' )
}

# fzf greenclip
grf(){
     # greenclip print | sed '/^$/d' | fzf -e | xargs -r -d'\n' -I '{}' greenclip print '{}'
     greenclip print | sed '/^$/d' | fzf -e | xargs -r -d'\n' -I '{}' greenclip print '{}'; sleep 0.5; xdotool type $(xclip -o -selection clipboard)
}

# dmenu greenclip
grd(){
    # greenclip print | sed '/^$/d' | dmenu -i -l 10 -p clipboard | xargs -r -d'\n' -I '{}' greenclip print '{}'
    greenclip print | sed '/^$/d' | dmenu -i -l 10 -p clipboard | xargs -r -d'\n' -I '{}' greenclip print '{}';sleep 0.5; xdotool type $(xclip -o -selection clipboard)
}

#  greenclip clear
grc(){
    pkill greenclip && greenclip clear && greenclip daemon &
}

## 终端命令行查英语单词
v2(){
  declare q="$*";
  #curl --user-agent curl "https://v2en.co/${q// /%20}";
  curl --user-agent curl "https://d.supjohn.com/${q// /%20}";

}
## v2-sh 可以直接进入交互模式，不用重复输入 v2 前缀
v2-sh(){
  while echo -n "v2en>";
  read -r input;
  [[ -n "$input" ]]
  do v2 "$input";
  done
}


# ranger 配置
## 会自动切换到最后一次浏览的目录.
# rangerhistory(){
ranger_cd() {
    temp_file="$(mktemp -t "ranger_cd.XXXXXXXXXX")"
    # ranger --choosedir="$temp_file" -- "${@:-$PWD}"        # 退出ranger后不会切换到最后停留的目录地址
    source ranger --choosedir="$temp_file" -- "${@:-$PWD}"   # 退出ranger后会切换到最后停留的目录地址
    if chosen_dir="$(cat -- "$temp_file")" && [ -n "$chosen_dir" ] && [ "$chosen_dir" != "$PWD" ]; then
        cd -- "$chosen_dir"
    fi
    rm -f -- "$temp_file"
}

# 使用rg和fzf搭配递归查找当前文件夹下内容
rg_fzf_find()
{
    # rg --column --smart-case  -- '' | fzf
    # rg --column --smart-case  -- '' | fzf --preview 'cat -n $( echo {} | cut -d : -f 1)'
    result=`rg --column --smart-case  -- '' | fzf --preview 'bat  $( echo {} | cut -d : -f 1)   --color=always  --wrap=auto  --style=numbers  --highlight-line=$(echo {} | cut -d : -f 2):$(echo {} | cut -d : -f 2)  --line-range=$(( $(( $(echo {} | cut -d : -f 2)-18 ))>18?$(( $(echo {} | cut -d : -f 2)-18 )):1 )):$(( $(echo {} | cut -d : -f 2)+18 ))  '`
    # echo "[Debug]=======${result}"
    if [ -f "$(echo ${result} | cut -d : -f 1)" ]; then
        vim  -o $(echo ${result} | cut -d : -f 1) + $(echo ${result} | cut -d : -f 2) 
    else
        echo "取消选择"
    fi
}

# rg 参数说明
# -M --max-depth 限制文件夹递归搜索深度。rg --max-depth 0 dir/则不执行任何搜索；rg --max-depth 1 dir/只在dir/当前目录中进行搜索。

# 使用ack和fzf搭配递归查找当前文件夹下内容
ack_fzf_find()
{
    # ack foo --js -A 2 -B 2 # 在当前目录下，查找js文件中包含foo文本，并打印与其相关的上下2行
    result=`ack -- '' | fzf --preview 'bat  $( echo {} | cut -d : -f 1)   --color=always  --wrap=auto  --style=numbers  --highlight-line=$(echo {} | cut -d : -f 2):$(echo {} | cut -d : -f 2)  --line-range=$(( $(( $(echo {} | cut -d : -f 2)-18 ))>18?$(( $(echo {} | cut -d : -f 2)-18 )):1 )):$(( $(echo {} | cut -d : -f 2)+18 ))  '`
    # echo "[Debug]=======${result}"
    # vim -o $(echo ${result} | cut -d : -f 1) +$(echo ${result} | cut -d : -f 2)
    if [ -f "$(echo ${result} | cut -d : -f 1)" ]; then
        vim -o $(echo ${result} | cut -d : -f 1) + $(echo ${result} | cut -d : -f 2) 
    else
        echo "取消选择"
    fi
}

alias r='ranger'
alias rc='source ranger'  # 退出ranger后会切换到最后停留的目录地址
alias rh='ranger_cd'

# 设置命令通用别名
alias cls='clear'
alias ll='ls -l'
alias la='ls -a'
alias vi='vim'
alias javac="javac -J-Dfile.encoding=utf8"
alias grep="grep --color=auto"

## 针对文件类型设置对应的打开程序
# alias -s html=mate               # 在命令行直接输入后缀为 html 的文件名，会在 TextMate 中打开，以下类似
# alias -s rb=mate                 # 在命令行直接输入 ruby 文件，会在 TextMate 中打开
alias -s py=vim                   # 在命令行直接输入 python 文件，会用 vim 中打开
alias -s js=vim                   # 在命令行直接输入 js 文件，会用 vim 中打开
alias -s c=vim                    # 在命令行直接输入 c 文件，会用 vim 中打开
alias -s java=vim                # 在命令行直接输入 java 文件，会用 vim 中打开
alias -s txt=vim                 # 在命令行直接输入 txt 文件，会用 vim 中打开

alias -s gz='tar -xzvf'          # 在命令行直接输入 文件名，会自动解压后缀为 gz 的压缩包
alias -s tgz='tar -xzvf'         # 在命令行直接输入 文件名，会自动解压后缀为 tgz 的压缩包
alias -s zip='unzip'             # 在命令行直接输入 文件名，会自动解压后缀为 zip 的压缩包
alias -s bz2='tar -xjvf'         # 在命令行直接输入 文件名，会自动解压后缀为 bz2 的压缩包

# 按 Ctrl-P 与 Ctrl-N 在历史命令记录搜索切换。
# bindkey '^P' history-search-backward
# bindkey '^N' history-search-forward
bindkey '^P' history-substring-search-up
bindkey '^N' history-substring-search-down

# zsh的vi-mode配置
bindkey -v
# zsh下模式切换模式光标变化（插入模式光标变成 细竖条  命令模式变为粗竖条 ）
function zle-keymap-select {
  if [[ ${KEYMAP} == vicmd ]] || [[ $1 = 'block' ]]; then
    echo -ne '\e[1 q'
  elif [[ ${KEYMAP} == main ]] || [[ ${KEYMAP} == viins ]] || [[ ${KEYMAP} = '' ]] || [[ $1 = 'beam' ]]; then
    echo -ne '\e[5 q'
  fi
}
zle -N zle-keymap-select

# Use beam shape cursor on startup. 开始时光标是细竖条
echo -ne '\e[5 q'

# Use beam shape cursor for each new prompt.
preexec() {
  echo -ne '\e[5 q'
}

_fix_cursor() {
  echo -ne '\e[5 q'
}
precmd_functions+=(_fix_cursor)

# vi-mode下历史命令搜索切换
bindkey -M vicmd 'k' history-substring-search-up
bindkey -M vicmd 'j' history-substring-search-down

# 热键绑定
# 查看当前绑定(使用 bindkey 命令即可)

# 常用默认按键
# ctrl + a，移动到行首
# ctrl + e，移动到行尾
# ctrl + f，前移一个字符
# ctrl + b，后移一个字符
# ctrl + w，删除光标前面的单词
# ctrl + d，删除光标所指的字符
# ctrl + k，删除光标至行尾的所有内容
# ctrl + u，清空当前行

# 在使用 bindkey 命令时，一帮第一个参数使用对应快捷键的 CSI 序列
#bindkey '\e[1;3D' backward-word       # ALT+左键   ：向后跳一个单词
#bindkey '\e[1;3C' forward-word        # ALT+右键   ：前跳一个单词
#bindkey '\e[1;3A' beginning-of-line   # ALT+上键   ：跳到行首
#bindkey '\e[1;3B' end-of-line         # ALT+下键   ：调到行尾

# Alt键+
#bindkey '\eh' backward-char
#bindkey '\el' forward-char
#bindkey '\ej' down-line-or-history
#bindkey '\ek' up-line-or-history

bindkey -s '\eo'   'cd ..\n'          # ALT+O      ：执行 cd .. 命令
bindkey -s '\e;'   'ls -l\n'          # ALT+;      ：执行 ls -l 命令
bindkey -s '\ef'   'rg_fzf_find\n'    # ALT+f      ：执行 rg_fzf_find 命令
# bindkey -s '\ef;' 'cdf\n'             # ALT+f;     ：执行 cdf 命令

# Ctrl键+
#bindkey '^h' backward-char            # Ctrl+f     ：向后跳一个单词
#bindkey '^l' forward-char             # Ctrl+f     ：前跳一个单词
#bindkey '^j' down-line-or-history     # Ctrl+f     ：下一个历史命令
#bindkey '^k' up-line-or-history       # Ctrl+f     ：上一个历史命令

#bindkey '^i' autosuggest-accept       # ctrl+.     ：将建议的历史填充到命令行输入 （默认使用方向右键）

bindkey -s '^g'    'git pull\n'       # Ctrl+f     ：执行 git pull 命令
# bindkey -s '^g'    'lazygit\n'        # Ctrl+g     ：执行 lazygit 命令
bindkey -s '^f'    'cdf\n'            # Ctrl+f     ：执行 cdf 命令
bindkey -s '^[f'   'rg_fzf_find\n'    # Ctrl+z+f   ：执行 rg_fzf_find 命令
bindkey -s '^af'   'ack_fzf_find\n'   # Ctrl+s+f   ：执行 ack_fzf_find 命令

# lf () {
#     LF_TEMPDIR="$(mktemp -d -t lf-tempdir-XXXXXX)"
#     LF_TEMPDIR="$LF_TEMPDIR" lf-run -last-dir-path="$LF_TEMPDIR/lastdir" "$@"
#     if [ "$(cat "$LF_TEMPDIR/cdtolastdir" 2>/dev/null)" -eq 1 ]; then
#         cd "$(cat "$LF_TEMPDIR/lastdir")"
#     fi
#     rm -r "$LF_TEMPDIR"
#     unset LF_TEMPDIR
# }
#alias lf='lf-ueberzug'        # 图片预览的LF
alias l='lf-ueberzug'        # 图片预览的LF
alias lc='lfcd'        # 图片预览的LF

[ -f ~/.config/lf/lfcd.sh ] && source ~/.config/lf/lfcd.sh
bindkey -s '^o' 'lfcd\n'  # Ctrl+o 进入lfcd的最后目录
